<template>
  <div class="v-count-up">{{ dispVlaue }}</div>
</template>
<script>
export default {
  data() {
    return {
      timer: "",
      calcValue: 0,
      startTime: 0,
      remaining: 0,
      raf: "",
    };
  },
  props: {
    value: Number,
    startValue: {
      type: Number,
      default: 0,
    },
    time: {
      type: Number,
      default: 5000,
    },
    useease: {
      type: Boolean,
      default: true,
    },
    tofixed: {
      type: Number,
      default: 0,
    },
    separator: {
      type: Boolean,
      default: false,
    },
    reset: {
      type: Boolean,
      default: false,
    },
  },
  computed: {
    dispVlaue() {
      const calcValue = (this.calcValue || 0).toFixed(this.tofixed);
      return this.separator ? this.formatNumber(calcValue) : calcValue;
    },
    startVal() {
      return this.startValue > this.value ? this.value : this.startValue;
    },
  },
  created() {
    this.start();
  },
  watch: {
    reset() {
      this._reset();
    },
  },
  methods: {
    count(timestamp) {
      if (!this.startTime) {
        this.startTime = timestamp;
      }
      let progress = timestamp - this.startTime;
      this.remaining = this.time - progress;
      if (this.useease) {
        this.calcValue = this.easeOutExpo(
          progress,
          this.startVal,
          this.value - this.startVal,
          this.time
        );
      } else {
        this.calcValue =
          this.startVal + (this.value - this.startVal) * (progress / this.time);
      }
      if (this.calcValue > this.value) {
        this.calcValue = this.value;
      }

      if (progress < this.time) {
        this.raf = requestAnimationFrame(this.count);
      } else {
        this.$emit("end");
        cancelAnimationFrame(this.raf);
      }
    },
    start() {
      if (this.time > 0) {
        this.raf = requestAnimationFrame(this.count);
      } else {
        this.printValue();
      }
    },

    _reset() {
      this.startTime = 0;
      this.calcValue = 0;
      this.remaining = 0;
      this.start();
    },

    easeOutExpo(t, b, c, d) {
      return (c * (-Math.pow(2, (-10 * t) / d) + 1) * 1024) / 1023 + b;
    },

    printValue() {
      this.calcValue = this.value;
    },

    formatNumber(num) {
      var result, x, x1, x2, x3;
      result = String(num);
      x = result.split(".");
      x1 = x[0];
      x2 = x.length > 1 ? "." + x[1] : "";
      if (this.separator) {
        x3 = "";
        for (var i = 0, len = x1.length; i < len; ++i) {
          if (i !== 0 && i % 3 === 0) {
            x3 = "," + x3;
          }
          x3 = x1[len - i - 1] + x3;
        }
        x1 = x3;
      }
      return x1 + x2;
    },
  },
  destroyed() {
    cancelAnimationFrame(this.raf);
  },
};
</script>
